March 20, 2021
그동안 카드 뒤집어서 짝맞추기, 지뢰찾기 등 게임 몇 개를 만들어봤는데 디자인에는 크게 신경을 쓰지 않았었다. 기능이 중요하지!! 하면서… 그렇지만 오늘은 유튜브에서 본 간단한 점프게임을 만들면서 이쁘게 꾸며보았다. 흡족하다. 이미지는 Pixabay에서 다운받았다. 만들면서 든 생각인데 슈퍼마리오 클론코딩하면 엄청 재밌을 것 같다.
호스팅은 파이어베이스를 이용했다.
(클릭 시 새 창에 뜹니다.)
https://jump-game-ac50b.web.app/
시작화면
폭탄이 다가오면 점프! 마우스로 화면을 클릭하면 된다.
게임이 끝나면 애니메이션이 멈추고 게임오버 텍스트가 뜬다.
만들면서 신경 쓴 부분들을 중점으로 설명해 보겠습니다.
<body>
<div id="game">
<div id="jumpNum" class="hidden">성공 × <span>0</span></div>
<div id="gameover" class="hidden">GAME OVER</div>
<button id="btn">Start</button>
<div id="character"></div>
<div id="bomb"></div>
</div>
</body>
html은 간단하다. 캐릭터와 폭탄은 div에 background-img로 넣어주었다.
#gameover {
position: absolute;
top: 100px;
left: 50%;
transform: translateX(-50%);
font-size: 3rem;
font-weight: bolder;
filter: drop-shadow(2px 2px rgb(124, 97, 97));
animation: twinkle 0.5s linear 2;
}
@keyframes twinkle {
0% {
opacity: 0.2;
}
50% {
opacity: 1;
}
100% {
opacity: 0.2;
}
}
레딧에서 누군가 말했었다. 본인 프로젝트에 음 뭔가 부족한데.. 싶으면 shadow를 추가해보라고. 그걸 본 뒤로 잘 애용하고 있다.
텍스트가 화면의 가운데에 있어야 하기 때문에 left: 50%, transform: translateX(-50%) 를 주었다.
애니메이션을 주어서 게임오버 텍스트가 빤짝빤짝 빛나게 했다.
#character {
position: relative;
top: 203px;
left: -55px;
background: url('./images/pacman.png') -357px -178px no-repeat;
width: 250px;
height: 270px;
transform: scale(0.45);
}
.jump {
animation: jump 1s ease;
}
@keyframes jump {
0% {
top: 203px;
}
50% {
top: 110px;
}
75% {
top: 110px;
}
100% {
top: 203px;
}
}
background position
을 조정해서 이미지 스프라이트를 하였다.
jump 클래스를 넣었다 붙였다 하면서 캐릭터가 점프하도록 만들 것이다.
jump 애니메이션에 50%와 75%를 똑같이 준 이유는 붕~ 뜨고 잠시 있다가 가라앉는 모션을 위해서이다.
startBtn.addEventListener('click', e => {
e.stopPropagation()
stopflag = false
bomb.classList.add('move')
gameoverText.classList.add('hidden')
startBtn.classList.add('hidden')
jumpNum.classList.remove('hidden')
jumpNumCnt.textContent = 0
})
stopPropagation()
을 줘서 start 버튼을 눌렀을 때 그 이벤트가 부모로 전달이 되지 않게끔 막았다. 이 코드를 삭제한다면 start 버튼을 누르면 캐릭터가 점프한다. 왜냐면 화면 아무 곳이나 누르면 점프하기 때문이다. 이 코드로 시작버튼을 클릭할 때 엄하게 캐릭터가 뛰는 것을 막을 수 있다.
게임오버 글씨나 재시작 버튼은 게임이 끝나면 보이고 시작하면 사라지도록 hidden 클래스를 넣었다 뺐다 한다. hidden 클래스에는 display: none
을 넣어주었다.
game.addEventListener('click', e => {
if (!stopflag) {
character.classList.add('jump')
stopflag = true
jumpNumCnt.textContent++
} else if (stopflag) {
return
}
// 연속으로 캐릭터가 뛰지 않도록 조절
setTimeout(() => {
character.classList.remove('jump')
stopflag = false
}, 1000)
})
클릭! -> 캐릭터 점프 시작 -> 착지. 점프 시작과 착지 사이에 또 클릭이 먹히면 안 된다. 그래서 stopflag 를 주어서 stopflag 가 true 라면 클릭을 무시하도록 return 을 주었다.
setTimeout
으로 1초 뒤에 jump 클래스를 제거했다.
setInterval(() => {
let characterTop = parseInt(
window.getComputedStyle(character).getPropertyValue('top')
)
let bombLeft = parseInt(
window.getComputedStyle(bomb).getPropertyValue('left')
)
// 졌다.
if (characterTop > 180 && bombLeft < -470) {
stopflag = true
bomb.classList.remove('move')
gameoverText.classList.remove('hidden')
startBtn.textContent = 'Replay'
setTimeout(() => {
startBtn.classList.remove('hidden')
}, 1000)
}
}, 100)
setInterval
로 0.1초마다 캐릭터와 폭탄이 닿았는지 확인한다.
window.getComputedStyle()
은 괄호 안의 css style 을 가져온다. 캐릭터의 높이와 폭탄의 좌측거리를 계산해서 충분히 높이 뛰지 않았는데 폭탄이 올 경우 게임이 종료된다.
게임이 종료될 때 바로 성공횟수를 0으로 초기화하면 사용자가 놓칠 수 있어서 재시작버튼을 누를 때 초기화하도록 했다.